// 设备树解析实现
// Device Tree Blob (DTB) parsing implementation

#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "riscv.h"
#include "spinlock.h"
#include "proc.h"
#include "dtb.h"
#include "defs.h"

static struct dtb_context dtb_ctx;
static struct device_info devices[32];  // 最多32个设备
static int device_count = 0;

// 简单的字符串查找函数
static char *
simple_strstr(const char *haystack, const char *needle) {
    if (!*needle) return (char*)haystack;
    
    for (; *haystack; haystack++) {
        const char *h = haystack;
        const char *n = needle;
        
        while (*h && *n && (*h == *n)) {
            h++;
            n++;
        }
        
        if (!*n) return (char*)haystack;
    }
    return 0;
}

// 大端字节序转换为小端字节序
// 设备树（Device Tree）通常使用大端字节序，RISC-V等现代CPU通常使用小端字节序
static uint32 be32_to_cpu(uint32 val) {
    return ((val & 0xff) << 24) | 
           ((val & 0xff00) << 8) | 
           ((val & 0xff0000) >> 8) | 
           ((val & 0xff000000) >> 24);
}

// 初始化DTB解析器
void dtb_init(void *dtb_addr) {
    // printf("DTB: Initializing device tree parser at 0x%lx\n", (uint64)dtb_addr);
    // 设备树头结构
    struct fdt_header *header = (struct fdt_header *)dtb_addr;
    
    // 验证魔数
    if (be32_to_cpu(header->magic) != 0xd00dfeed) {
        // printf("DTB: Invalid magic number: 0x%x\n", be32_to_cpu(header->magic));
        return;
    }
    
    // printf("DTB: Valid device tree found\n");
    // printf("DTB: Total size: %d bytes\n", be32_to_cpu(header->totalsize));
    // printf("DTB: Version: %d\n", be32_to_cpu(header->version));
    
    // 初始化解析上下文
    dtb_ctx.dtb_start = (char *)dtb_addr;
    dtb_ctx.struct_start = dtb_ctx.dtb_start + be32_to_cpu(header->off_dt_struct);
    dtb_ctx.strings_start = dtb_ctx.dtb_start + be32_to_cpu(header->off_dt_strings);
    dtb_ctx.struct_size = be32_to_cpu(header->size_dt_struct);
    dtb_ctx.strings_size = be32_to_cpu(header->size_dt_strings);
    dtb_ctx.current_offset = 0;
    
    device_count = 0;
}

// 读取32位大端数据
uint32 dtb_read_u32(struct dtb_context *ctx, uint32 offset) {
    if (offset + 4 > ctx->struct_size) {
        return 0;
    }
    uint32 *ptr = (uint32 *)(ctx->struct_start + offset);
    return be32_to_cpu(*ptr);
}

// 根据dtb字符串偏移获取字符串指针
char *dtb_get_string(struct dtb_context *ctx, uint32 offset) {
    if (offset >= ctx->strings_size) {
        return "invalid_string";
    }
    return ctx->strings_start + offset;
}

// 对齐到4字节边界
static uint32 align_4(uint32 val) {
    return (val + 3) & ~3;
}

// 解析属性值中的地址和大小
static void parse_reg_property(char *data, uint32 len, uint64 *base, uint64 *size) {
    if (len >= 16) {
        // 假设地址单元大小为2，大小单元大小为2 (64位地址，64位大小)
        uint32 *cells = (uint32 *)data;
        *base = ((uint64)be32_to_cpu(cells[0]) << 32) | be32_to_cpu(cells[1]);
        *size = ((uint64)be32_to_cpu(cells[2]) << 32) | be32_to_cpu(cells[3]);
    } else if (len >= 8) {
        // 32位地址和大小
        uint32 *cells = (uint32 *)data;
        *base = be32_to_cpu(cells[0]);
        *size = be32_to_cpu(cells[1]);
    }
}

// 解析中断属性
static uint32 parse_interrupts_property(char *data, uint32 len) {
    if (len >= 4) {
        uint32 *cells = (uint32 *)data;
        return be32_to_cpu(cells[0]);
    }
    return 0;
}

// 解析设备树
int dtb_parse(void) {
    // printf("DTB: Starting device tree parsing\n");
    
    uint32 offset = 0;
    int path_depth = 0;
    struct device_info *current_device = 0;
    
    while (offset < dtb_ctx.struct_size) {
        // 读取当前偏移量处的token
        uint32 token = dtb_read_u32(&dtb_ctx, offset);
        offset += 4;
        
        switch (token) {
            // 开始节点
            case FDT_BEGIN_NODE: {
                // 读取当前设备名称
                char *node_name = dtb_ctx.struct_start + offset;
                // for(int i = 0; i < path_depth; i++) {
                //     printf("  ");
                // }
                // printf("DTB: Found node: %s\n", node_name);
                
                // 如果设备数量未达到上限，创建新设备信息
                if (device_count < 32) {
                    current_device = &devices[device_count];
                    memset(current_device, 0, sizeof(struct device_info));
                    // 将当前设备名称拷贝到设备信息结构体中
                    safestrcpy(current_device->name, node_name, sizeof(current_device->name));
                }
                
                // 跳过设备名称
                offset = align_4(offset + strlen(node_name) + 1);
                path_depth++;
                break;
            }
            // 结束节点
            case FDT_END_NODE:
                // 如果当前设备有效，增加设备计数
                if (current_device && current_device->valid) {
                    device_count++;
                    // for(int i = 0; i < path_depth; i++) {
                    //     printf("  ");
                    // }
                    // printf("DTB: Added device: %s\n", current_device->name);
                }
                current_device = 0;
                path_depth--;
                break;
            // 属性
            case FDT_PROP: {
                if (offset + 8 > dtb_ctx.struct_size) break;
                
                struct fdt_prop prop;
                // 读取属性长度地址
                prop.len = dtb_read_u32(&dtb_ctx, offset);
                // 读取属性名称
                prop.nameoff = dtb_read_u32(&dtb_ctx, offset + 4);
                char *prop_name = dtb_get_string(&dtb_ctx, prop.nameoff);
                // 读取属性
                offset += 8;
                char *prop_data = dtb_ctx.struct_start + offset;
                
                if (current_device) {
                    // 解析compatible属性
                    if (strcmp(prop_name, "compatible") == 0) {
                        safestrcpy(current_device->compatible, prop_data, prop.len < sizeof(current_device->compatible) ? prop.len : sizeof(current_device->compatible) - 1);
                        current_device->valid = 1;
                        // for(int i = 0; i < path_depth; i++) {
                        //     printf("  ");
                        // }
                        // printf("DTB: Compatible: %s\n", current_device->compatible);
                    }
                    // 解析reg属性
                    else if (strcmp(prop_name, "reg") == 0) {
                        parse_reg_property(prop_data, prop.len, &current_device->reg_base, &current_device->reg_size);
                        // for(int i = 0; i < path_depth; i++) {
                        //     printf("  ");
                        // }
                        // printf("DTB: Reg: base=0x%lx, size=0x%lx\n", current_device->reg_base, current_device->reg_size);
                    }
                    // 解析interrupts属性
                    else if (strcmp(prop_name, "interrupts") == 0) {
                        current_device->interrupt = parse_interrupts_property(prop_data, prop.len);
                        // for(int i = 0; i < path_depth; i++) {
                        //     printf("  ");
                        // }
                        // printf("DTB: Interrupt: %d\n", current_device->interrupt);
                    }
                }
                
                // 跳过属性数据
                offset = align_4(offset + prop.len);
                break;
            }
            // 空操作
            case FDT_NOP:
                break;
            // 结束
            case FDT_END:
                // printf("DTB: Parsing completed. Found %d devices\n", device_count);
                return device_count;
            default:
                // printf("DTB: Unknown token: 0x%x at offset 0x%x\n", token, offset - 4);
                return -1;
        }
    }
    
    // printf("DTB: Parsing completed unexpectedly\n");
    return device_count;
}

// 根据compatible查找设备
struct device_info *dtb_find_device(const char *compatible, int interrupt) {
    for (int i = 0; i < device_count; i++) {
        if (devices[i].valid && simple_strstr(devices[i].compatible, compatible)) {
            if (interrupt != -1 && devices[i].interrupt != interrupt) {
                continue;
            }
            return &devices[i];
        }
    }
    return 0;
}

// 打印所有已解析的设备
void dtb_print_devices(void) {
    printf("DTB: Parsed devices (%d total):\n", device_count);
    for (int i = 0; i < device_count; i++) {
        if (devices[i].valid) {
            printf("  Device %d: %s\n", i, devices[i].name);
            printf("    Compatible: %s\n", devices[i].compatible);
            printf("    Base: 0x%lx, Size: 0x%lx\n", devices[i].reg_base, devices[i].reg_size);
            printf("    Interrupt: %d\n", devices[i].interrupt);
        }
    }
}
